/* Copyright (c) 2009-2013 Olivier Chafik, All Rights Reserved This file is part of JNAerator (http://jnaerator.googlecode.com/). JNAerator is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JNAerator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with JNAerator. If not, see <http://www.gnu.org/licenses/>. */ package com.ochafik.lang.jnaerator; import com.ochafik.lang.SyntaxUtils; import com.ochafik.lang.jnaerator.JNAeratorConfig.GenFeatures; import static com.ochafik.lang.jnaerator.TypeConversion.ConvType; import static com.ochafik.lang.jnaerator.TypeConversion.JavaPrim; import com.ochafik.lang.jnaerator.parser.*; import com.ochafik.lang.jnaerator.parser.Declarator.ArrayDeclarator; import com.ochafik.lang.jnaerator.parser.Declarator.MutableByDeclarator; import static com.ochafik.lang.jnaerator.parser.ElementsHelper.*; import com.ochafik.lang.jnaerator.parser.Enum; import com.ochafik.lang.jnaerator.parser.Enum.EnumItem; import com.ochafik.lang.jnaerator.parser.Expression.Constant; import com.ochafik.lang.jnaerator.parser.Expression.MemberRef; import com.ochafik.lang.jnaerator.parser.Expression.MemberRefStyle; import com.ochafik.lang.jnaerator.parser.Expression.TypeRefExpression; import com.ochafik.lang.jnaerator.parser.Identifier.SimpleIdentifier; import com.ochafik.lang.jnaerator.parser.StoredDeclarations.TypeDef; import com.ochafik.lang.jnaerator.parser.TypeRef.ArrayRef; import com.ochafik.lang.jnaerator.parser.TypeRef.FunctionSignature; import com.ochafik.lang.jnaerator.parser.TypeRef.Pointer; import com.ochafik.lang.jnaerator.parser.TypeRef.Primitive; import com.ochafik.lang.jnaerator.parser.TypeRef.SimpleTypeRef; import com.ochafik.lang.jnaerator.parser.TypeRef.TaggedTypeRef; import com.ochafik.lang.jnaerator.parser.TypeRef.TargettedTypeRef; import com.ochafik.lang.jnaerator.runtime.CGFloatByReference; import com.ochafik.lang.jnaerator.runtime.CharByReference; import com.ochafik.lang.jnaerator.runtime.NativeSize; import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; import com.ochafik.lang.jnaerator.runtime.globals.Global; import com.ochafik.lang.jnaerator.runtime.globals.GlobalByte; import com.ochafik.lang.jnaerator.runtime.globals.GlobalCGFloat; import com.ochafik.lang.jnaerator.runtime.globals.GlobalChar; import com.ochafik.lang.jnaerator.runtime.globals.GlobalDouble; import com.ochafik.lang.jnaerator.runtime.globals.GlobalFloat; import com.ochafik.lang.jnaerator.runtime.globals.GlobalInt; import com.ochafik.lang.jnaerator.runtime.globals.GlobalLong; import com.ochafik.lang.jnaerator.runtime.globals.GlobalNativeLong; import com.ochafik.lang.jnaerator.runtime.globals.GlobalNativeSize; import com.ochafik.lang.jnaerator.runtime.globals.GlobalShort; import com.nativelibs4java.jalico.Pair; import com.ochafik.util.string.StringUtils; import com.sun.jna.Native; import com.sun.jna.WString; import com.sun.jna.ptr.ByReference; import com.sun.jna.ptr.ByteByReference; import com.sun.jna.ptr.DoubleByReference; import com.sun.jna.ptr.FloatByReference; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.LongByReference; import com.sun.jna.ptr.NativeLongByReference; import com.sun.jna.ptr.PointerByReference; import com.sun.jna.ptr.ShortByReference; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.regex.Pattern; import org.bridj.util.DefaultParameterizedType; import org.rococoa.ObjCClass; import org.rococoa.ObjCObject; import org.rococoa.cocoa.foundation.NSObject; public abstract class TypeConversion implements ObjCppParser.ObjCParserHelper { Result result; public boolean allowUnknownPointers = true, allowFakePointers = false; public TypeConversion(Result result) { super(); this.result = result; initTypes(); } //public Set<Identifier> fakePointersSink; public enum TypeConversionMode { PrimitiveOrBufferParameter, NativeParameter, NativeParameterWithStructsPtrPtrs, FieldType, ReturnType, ExpressionType, StaticallySizedArrayField, PrimitiveReturnType, PointedValue } public Map<JavaPrim, Class<? extends ByReference>> primToByReference = new LinkedHashMap<JavaPrim, Class<? extends ByReference>>(); public Map<JavaPrim, Class<? extends Global>> primToGlobal = new LinkedHashMap<JavaPrim, Class<? extends Global>>(); public Map<JavaPrim, Class<? extends Buffer>> primToBuffer = new LinkedHashMap<JavaPrim, Class<? extends Buffer>>(); public final Set<String> byReferenceClassesNames = new HashSet<String>(); public boolean isObjCppPrimitive(String s) { return result.isObjCppPrimitive(s); } public enum JavaPrim { Void(java.lang.Void.TYPE, null, ESize.Zero), Char(Character.TYPE, Character.class, ESize.CharSize), Long(java.lang.Long.TYPE, java.lang.Long.class, ESize.Eight), Int(Integer.TYPE, Integer.class, ESize.Four), Short(java.lang.Short.TYPE, java.lang.Short.class, ESize.Two), Byte(java.lang.Byte.TYPE, java.lang.Byte.class, ESize.One), Boolean(java.lang.Boolean.TYPE, java.lang.Boolean.class, ESize.One), Float(java.lang.Float.TYPE, java.lang.Float.class, ESize.Four), Double(java.lang.Double.TYPE, java.lang.Double.class, ESize.Eight), ComplexDouble(null, null, ESize.Sixteen), NativeLong(com.sun.jna.NativeLong.class, com.sun.jna.NativeLong.class, ESize.StaticSizeField), NativeSize(NativeSize.class, NativeSize.class, ESize.StaticSizeField), NativeTime(null, null, ESize.StaticSizeField), NSInteger(org.rococoa.cocoa.foundation.NSInteger.class, org.rococoa.cocoa.foundation.NSInteger.class, ESize.StaticSizeField), NSUInteger(org.rococoa.cocoa.foundation.NSUInteger.class, org.rococoa.cocoa.foundation.NSUInteger.class, ESize.StaticSizeField), CGFloat(org.rococoa.cocoa.CGFloat.class, org.rococoa.cocoa.CGFloat.class, ESize.StaticSizeField); public final Class<?> type, wrapperType; public final String simpleName, name; public final boolean isPrimitive; public enum ESize { One(expr(1)), Two(expr(2)), Four(expr(4)), Eight(expr(8)), Sixteen(expr(16)), StaticSizeField(null) { @Override public Expression sizeof(JavaPrim p) { return staticField(p.type, "SIZE"); } }, CharSize(null) { @Override public Expression sizeof(JavaPrim p) { return staticField(Native.class, "WCHAR_SIZE"); } }, Zero(expr(0)); private final Expression sizeOfExpression; ESize(Expression sizeOfExpression) { this.sizeOfExpression = sizeOfExpression; } public Expression sizeof(JavaPrim p) { return sizeOfExpression.clone(); } } public final ESize size; private static Map<String, JavaPrim> nameToPrim; public static JavaPrim getJavaPrim(String name) { if (nameToPrim == null) { nameToPrim = new LinkedHashMap<String, JavaPrim>(); for (JavaPrim p : values()) { nameToPrim.put(p.simpleName, p); } } return nameToPrim.get(name); } JavaPrim(Class<?> type, Class<?> wrapperType, ESize size) { this.type = type; this.wrapperType = wrapperType; this.size = size; this.name = type == null ? null : type.getName(); this.isPrimitive = type == null || type.isPrimitive(); this.simpleName = type == null ? null : type.getSimpleName(); } } protected TypeRef functionPointerTypeRef(TypeRef.FunctionSignature fs) { return fs; } protected TypeRef pointerTypeRef(TypeRef targetTypeRef) { return typeRef(result.config.runtime.pointerClass); } public Expression typeLiteral(TypeRef c) { if (c == null) { return null; } if (c.toString().equals("?")) { return new Expression.Cast(typeRef(Type.class), Constant.newNull()); } return memberRef(expr(c), MemberRefStyle.Dot, "class"); } protected abstract JavaPrim getCppBoolMappingType(); public void initTypes() { result.prim("void", JavaPrim.Void); result.prim("VOID", JavaPrim.Void); result.prim("UTF32Char", JavaPrim.Int); result.prim("unichar", JavaPrim.Char); result.prim("int64_t", JavaPrim.Long); result.prim("uint64_t", JavaPrim.Long); result.prim("u_int64_t", JavaPrim.Long); result.prim("long long", JavaPrim.Long); result.prim("long long int", JavaPrim.Long); result.prim("long int", JavaPrim.Int); result.prim("LONGLONG", JavaPrim.Long); result.prim("ULONGLONG", JavaPrim.Long); result.prim("INT", JavaPrim.Int); result.prim("UINT", JavaPrim.Int); result.prim("SHORT", JavaPrim.Short); result.prim("USHORT", JavaPrim.Short); result.prim("CHAR", JavaPrim.Byte); result.prim("byte", JavaPrim.Byte); result.prim("BYTE", JavaPrim.Byte); result.prim("UBYTE", JavaPrim.Byte); result.prim("DOUBLE", JavaPrim.Double); result.prim("FLOAT", JavaPrim.Float); result.prim("WORD", JavaPrim.Short); result.prim("DWORD", JavaPrim.Int); result.prim("DWORD64", JavaPrim.Long); result.prim("LONG64", JavaPrim.Long); result.prim("UInt64", JavaPrim.Long); result.prim("SInt64", JavaPrim.Long); result.prim("__int64", JavaPrim.Long); result.prim("__int64_t", JavaPrim.Long); result.prim("int32_t", JavaPrim.Int); result.prim("uint32_t", JavaPrim.Int); result.prim("__int32_t", JavaPrim.Int); result.prim("__uint32_t", JavaPrim.Int); result.prim("u_int32_t", JavaPrim.Int); result.prim("uint32", JavaPrim.Int); result.prim("int32", JavaPrim.Int); result.prim("int", JavaPrim.Int); //prim("NSUInteger", JavaPrim.NativeSize); //prim("NSInteger", JavaPrim.NativeSize); result.prim("SInt32", JavaPrim.Int); result.prim("UInt32", JavaPrim.Int); result.prim("GLint", JavaPrim.Int); result.prim("GLuint", JavaPrim.Int); result.prim("GLenum", JavaPrim.Int); result.prim("GLsizei", JavaPrim.Int); result.prim("__int32", JavaPrim.Int); result.prim("NSInteger", JavaPrim.NSInteger); result.prim("NSUInteger", JavaPrim.NSUInteger); result.prim("CGFloat", JavaPrim.CGFloat); JavaPrim longPrim = result.config.gccLong ? JavaPrim.NativeSize : JavaPrim.NativeLong; result.prim("long", longPrim); result.prim("LONG", longPrim); result.prim("ULONG", longPrim); result.prim("time_t", JavaPrim.NativeTime); JavaPrim sizePrim = result.config.sizeAsLong ? longPrim : JavaPrim.NativeSize; result.prim("size_t", sizePrim); result.prim("ptrdiff_t", sizePrim); result.prim("__darwin_size_t", JavaPrim.NativeSize); result.prim("complex double", JavaPrim.ComplexDouble); result.prim("int16_t", JavaPrim.Short); result.prim("uint16_t", JavaPrim.Short); result.prim("__int16_t", JavaPrim.Short); result.prim("__uint16_t", JavaPrim.Short); result.prim("u_int16_t", JavaPrim.Short); result.prim("uint16", JavaPrim.Short); result.prim("int16", JavaPrim.Short); result.prim("SInt16", JavaPrim.Short); result.prim("UInt16", JavaPrim.Short); result.prim("short", JavaPrim.Short); result.prim("WCHAR", JavaPrim.Short); result.prim("wchar_t", result.config.wcharAsShort ? JavaPrim.Short : JavaPrim.Char); result.prim("__int16", JavaPrim.Short); result.prim("int8_t", JavaPrim.Byte); result.prim("uint8_t", JavaPrim.Byte); result.prim("u_int8_t", JavaPrim.Byte); result.prim("__uint8_t", JavaPrim.Byte); result.prim("__int8_t", JavaPrim.Byte); result.prim("SInt8", JavaPrim.Byte); result.prim("UInt8", JavaPrim.Byte); result.prim("char", JavaPrim.Byte); result.prim("unsigned char", JavaPrim.Byte); result.prim("__unsigned char", JavaPrim.Byte); result.prim("signed char", JavaPrim.Byte); result.prim("__signed char", JavaPrim.Byte); result.prim("SignedByte", JavaPrim.Byte); result.prim("__int8", JavaPrim.Byte); result.prim("float", JavaPrim.Float); result.prim("NSFloat", JavaPrim.Float); result.prim("CGFloat", JavaPrim.Float); result.prim("double_t", JavaPrim.Double); result.prim("double", JavaPrim.Double); result.prim("NSDouble", JavaPrim.Double); result.prim("CGDouble", JavaPrim.Double); JavaPrim cppBoolType = getCppBoolMappingType(); result.prim("bool", cppBoolType); result.prim("Boolean", cppBoolType); result.prim("boolean_t", cppBoolType); primToByReference.put(JavaPrim.Int, IntByReference.class); primToByReference.put(JavaPrim.Char, (Class) CharByReference.class); primToByReference.put(JavaPrim.Short, ShortByReference.class); primToByReference.put(JavaPrim.Byte, ByteByReference.class); primToByReference.put(JavaPrim.Long, LongByReference.class); primToByReference.put(JavaPrim.Float, FloatByReference.class); primToByReference.put(JavaPrim.Double, DoubleByReference.class); primToByReference.put(JavaPrim.NativeLong, NativeLongByReference.class); primToByReference.put(JavaPrim.NativeSize, (Class) NativeSizeByReference.class); primToByReference.put(JavaPrim.NSInteger, (Class) NativeSizeByReference.class); primToByReference.put(JavaPrim.NSUInteger, (Class) NativeSizeByReference.class); primToByReference.put(JavaPrim.CGFloat, CGFloatByReference.class); //primsByReference.put(JavaPrim.Void, PointerByReference.class); for (Class<?> c : primToByReference.values()) { byReferenceClassesNames.add(c.getName()); } // byReferenceClassesNames.add(PointerByReference.class.getName()); primToGlobal.put(JavaPrim.Int, GlobalInt.class); primToGlobal.put(JavaPrim.Char, GlobalChar.class); primToGlobal.put(JavaPrim.Short, GlobalShort.class); primToGlobal.put(JavaPrim.Byte, GlobalByte.class); primToGlobal.put(JavaPrim.Long, GlobalLong.class); primToGlobal.put(JavaPrim.Float, GlobalFloat.class); primToGlobal.put(JavaPrim.Double, GlobalDouble.class); primToGlobal.put(JavaPrim.NativeLong, GlobalNativeLong.class); primToGlobal.put(JavaPrim.NativeSize, GlobalNativeSize.class); primToGlobal.put(JavaPrim.NSInteger, GlobalNativeSize.class); primToGlobal.put(JavaPrim.NSUInteger, GlobalNativeSize.class); primToGlobal.put(JavaPrim.CGFloat, GlobalCGFloat.class); primToBuffer.put(JavaPrim.Int, IntBuffer.class); primToBuffer.put(JavaPrim.Char, CharBuffer.class); primToBuffer.put(JavaPrim.Short, ShortBuffer.class); primToBuffer.put(JavaPrim.Byte, ByteBuffer.class); primToBuffer.put(JavaPrim.Long, LongBuffer.class); primToBuffer.put(JavaPrim.Float, FloatBuffer.class); primToBuffer.put(JavaPrim.Double, DoubleBuffer.class); //primToBuffer.put(JavaPrim.NativeLong, NativeLongByReference.class); TypeRef pInt = new TypeRef.Pointer(new Primitive("int"), Declarator.PointerStyle.Pointer); result.addManualTypeDef("intptr_t", pInt); result.addManualTypeDef("uintptr_t", pInt); // TODO: Add a windows failsafe mode that defines all the typedefs needed: // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx // TypeRef pVoid = new TypeRef.Pointer(new Primitive("void"), Declarator.PointerStyle.Pointer); // result.addManualTypeDef("PVOID", pVoid); // result.addManualTypeDef("LPVOID", pVoid); // result.addManualTypeDef("LPCVOID", pVoid); } protected TypeRef findTypeRef(Identifier name, Identifier libraryClassName) { TypeRef tr; tr = findStructRef(name, libraryClassName); if (tr != null) { return tr; } tr = findEnum(name, libraryClassName); if (tr != null) { return tr; } tr = findCallbackRef(name, libraryClassName); if (tr != null) { return tr; } tr = findObjCClass(name); if (tr != null) { return tr; } tr = result.manualTypeDefs.get(name); if (tr != null) { return tr; } return null; } public TypeRef normalizeTypeRef(TypeRef tr) { return normalizeTypeRef(tr, new HashSet<Identifier>()); } public TypeRef normalizeTypeRef(TypeRef tr, HashSet<Identifier> resolvedNames) { if (tr instanceof TypeRef.SimpleTypeRef) { Identifier name = ((TypeRef.SimpleTypeRef)tr).getName(); // if (isObjCppPrimitive(name.toString())) { // return tr; // } TypeRef td = resolvedNames.add(name) ? result.getTypeDef(name) : null; if (td != null) return normalizeTypeRef(td, resolvedNames); Struct s = result.resolveStruct(name); if (s != null) return s; Enum e = result.resolveEnum(name); if (e != null) return e; TypeRef.FunctionSignature c = result.resolveCallback(name); if (c != null) return functionPointerTypeRef(c); } if (tr instanceof TypeRef.TargettedTypeRef) { TypeRef.TargettedTypeRef ttr = (TypeRef.TargettedTypeRef) tr; TypeRef target = ttr.getTarget(); TypeRef ntarget = normalizeTypeRef(target, resolvedNames); if (ntarget != target) { ttr = (TypeRef.TargettedTypeRef) ttr.clone(); ttr.setTarget(target); } return ttr; } if (tr instanceof TaggedTypeRef) { TaggedTypeRef ttr = (TaggedTypeRef) tr; if (ttr.isForwardDeclaration()) { Identifier name = ttr.getTag(); if (ttr instanceof Struct) { ttr = result.resolveStruct(name); } else if (ttr instanceof Enum) { ttr = result.resolveEnum(name); } if (ttr != null) return ttr; } } return tr; } public static class JavaPrimitive extends Primitive { JavaPrim javaPrim; public JavaPrimitive() { } public JavaPrimitive(JavaPrim javaPrim) { super(); setName(ident(javaPrim == JavaPrim.Void ? Void.TYPE : javaPrim.type)); this.javaPrim = javaPrim; } public JavaPrim getJavaPrim() { return javaPrim; } public void setJavaPrim(JavaPrim javaPrim) { this.javaPrim = javaPrim; } } public JavaPrim getPrimitive(TypeRef valueType) { if (!(valueType instanceof Primitive) && !(valueType instanceof JavaPrimitive)) { valueType = normalizeTypeRef(valueType); } if (valueType == null) { return null; } Identifier name = null; List<Modifier> mods = valueType.getModifiers(); int longCount = ModifierType.Long.countIn(mods); if (valueType instanceof JavaPrimitive) { return ((JavaPrimitive) valueType).getJavaPrim(); } if (valueType instanceof Primitive) { name = ((Primitive) valueType).getName(); if (name == null) { if (longCount == 1) { name = ident("long"); } else if (longCount > 1) { name = ident("long long"); } else if (valueType.hasModifier(ModifierType.Short)) { name = ident("short"); } else { name = ident("int"); } } } else if (valueType instanceof SimpleTypeRef) { name = ((SimpleTypeRef) valueType).getName(); } if (name == null) { return null; } JavaPrim p = JavaPrim.getJavaPrim(name.toString()); if (p != null && !p.isPrimitive) { return p; } boolean isLong = false; String str; // if ((isLong = valueType.hasModifier(ModifierType.Long)) || valueType.hasModifier(ModifierType.Short)) { // //if ((isLong = valueType.hasModifier(ModifierType.Long)) || valueType.hasModifier(ModifierType.Short)) { // str = (isLong ? "long " : "short ") + name; // } else { str = name.toString(); // } JavaPrim type = result.resolvePrimitive(str); if ((type == JavaPrim.Int || type == JavaPrim.NativeLong) && longCount >= 1) { return JavaPrim.Long; } if (type == JavaPrim.Double && valueType.hasModifier(ModifierType._Complex)) { return JavaPrim.ComplexDouble; } return type; } public SimpleTypeRef findStructRef(Identifier name, Identifier libraryClassName) { return findStructRef(result.resolveStruct(name), libraryClassName); } public SimpleTypeRef findStructRef(Struct s, Identifier name, Identifier libraryClassName) { if (s == null || s.isForwardDeclaration()) { TypeRef td = result.getTypeDef(name); if (!(td instanceof Struct)) { return null; } s = (Struct) td; } if (s == null && result.config.runtime == JNAeratorConfig.Runtime.BridJ) { String ns = name.toString(); Class<?> cl = null; if (ns.equals("IUnknown")) { cl = org.bridj.cpp.com.IUnknown.class; } else if (ns.equals("GUID")) { cl = org.bridj.cpp.com.GUID.class; } else if (ns.equals("RECT")) { cl = org.bridj.cpp.com.RECT.class; } if (cl != null) { return typeRef(ident(cl)); } } return typeRef(getTaggedTypeIdentifierInJava(s)); /* name = result.declarationsConverter.getActualTaggedTypeName((TaggedTypeRef) pair.getFirst().getValueType()); return findRef(name, s, libraryClassName, !result.config.putTopStructsInSeparateFiles); } else { return result.getTaggedTypeIdentifierInJava(s); //name = result.declarationsConverter.getActualTaggedTypeName(s); }*/ } public SimpleTypeRef findStructRef(Struct s, Identifier libraryClassName) { if (s == null) { return null; } switch (s.getType()) { case ObjCClass: case ObjCProtocol: return typeRef(result.objectiveCGenerator.getFullClassName(s)); default: return findStructRef(s, result.declarationsConverter.getActualTaggedTypeName(s), libraryClassName); } } // public String find(String name, Element e, String callerLibraryClass) { // if (e == null) // return null; // String library = result.getLibrary(e); // if (library == null) // return null; // SimpleIdentifier libClass = result.getLibraryClassFullName(library); // return SyntaxUtils.equal(libClass, callerLibraryClass) ? name : libClass + "." + name; // } protected Identifier packageMember(Identifier libraryPackage, Identifier name) { return ident(libraryPackage, name); } protected Identifier libMember(Identifier libClass, Identifier libraryClassName, Identifier member) { //return ident(SyntaxUtils.equal(libClass, libraryClassName) ? null : libClass, member); return ident(libClass, member); //return member; //TODODODODODODODODOoOOOOO } public Identifier findRef(Identifier name, Element e, Identifier libraryClassName, boolean inLibClass) { if (e == null || !name.isPlain()) { return null; } String library = result.getLibrary(e); if (library == null) { return null; } // e = e.getParentElement(); Struct parentStruct = e instanceof Struct ? (Struct) e : e.findParentOfType(Struct.class); if (!inLibClass && parentStruct != null) { if (parentStruct == e) { return ident(result.getLibraryPackage(library), name); } return ident(getTaggedTypeIdentifierInJava(parentStruct), name); } return libMember(result.getLibraryClassFullName(library), libraryClassName, name); } public SimpleTypeRef findEnum(Identifier name, Identifier libraryClassName) { return findEnum(result.resolveEnum(name), libraryClassName); } public SimpleTypeRef findEnum(Enum s, Identifier libraryClassName) { if (s == null) { return null; } if (result.config.runtime == JNAeratorConfig.Runtime.BridJ) { return typeRef(getTaggedTypeIdentifierInJava(s)); } Identifier name = result.declarationsConverter.getActualTaggedTypeName(s); String library = result.getLibrary(s); if (library == null) { return null; } Identifier libClass = result.getLibraryClassFullName(library); SimpleTypeRef tr = new SimpleTypeRef("int"); if (result.config.features.contains(JNAeratorConfig.GenFeatures.EnumTypeLocationComments)) { tr.setCommentBefore("@see " + (SyntaxUtils.equal(libClass, libraryClassName) ? name : libClass + "#" + name)); } return tr; } public static Expression javaStaticFieldRef(Identifier javaClass, Identifier fieldName) { return memberRef( expr(typeRef(javaClass)), MemberRefStyle.Dot, fieldName); } public Expression findDefine(Identifier name) { Define s = result.defines.get(name); String library = s == null ? null : result.getLibrary(s); return library == null ? null : javaStaticFieldRef(result.getLibraryClassFullName(library), name); } public Identifier inferCallBackName(FunctionSignature functionSignature, boolean prependNamespaces, boolean qualify, Identifier libraryClassName) { List<String> nameElements = new ArrayList<String>(); Identifier name = functionSignature.getFunction().getName(); if (name != null) { name = name.clone(); } Identifier parentIdent = null; Element parent = functionSignature.getParentElement(); if (parent instanceof TypeRef.Pointer) parent = parent.getParentElement(); boolean firstParent = true; while (parent != null) { if (parent instanceof Struct) { SimpleTypeRef parentRef = findStructRef((Struct) parent, null); if (parentRef != null) { parentIdent = parentRef.getName(); break; } } if (firstParent) { if (name == null && parent instanceof TypeDef) { Declarator simpleSto = null; for (Declarator sto : ((TypeDef) parent).getDeclarators()) { String stoName = sto.resolveName(); if (stoName == null) { continue; } if (!(sto instanceof ArrayDeclarator)) { boolean weirdName = stoName.startsWith("_") || stoName.endsWith("_"); if (simpleSto == null || (simpleSto.resolveName().startsWith("_") || simpleSto.resolveName().endsWith("_")) && !weirdName) { simpleSto = sto; } if (!weirdName) { break; } } if (stoName != null) { name = new SimpleIdentifier(stoName); } } } else if (name == null && parent instanceof Arg) { Arg arg = (Arg) parent; Function f = SyntaxUtils.as(arg.getParentElement(), Function.class); if (f != null) { name = new SimpleIdentifier(f.getName() + "_" + arg.getName()); break; } } else if (firstParent) { // if (//parent instanceof VariablesDeclaration || // parent instanceof FunctionPointerDeclaration // //|| parent instanceof TypeDef // ) { // nameElements.add("Callback"); // } } } parent = parent.getParentElement(); firstParent = false; } if (qualify && parentIdent == null) { //if (libraryClassName != null) // parentIdent = libraryClassName; //else { String library = result.getLibrary(functionSignature); if (library != null) { parentIdent = result.getLibraryClassFullName(library); } //} } if (prependNamespaces) { if (name == null) { name = new SimpleIdentifier("callback"); } nameElements.add(name.toString()); return ident(qualify ? parentIdent : null, StringUtils.implode(nameElements, "_")); } else { return ident(qualify ? parentIdent : null, name); } } public TypeRef findCallbackRef(Identifier name, Identifier libraryClassName) { FunctionSignature s = result.resolveCallback(name); if (s == null) { return null; } // Struct parentStruct = s.findParentOfType(Struct.class); // if (parentStruct != null && (parentStruct.getType() == Struct.Type.ObjCClass || parentStruct.getType() == Struct.Type.ObjCProtocol)) { // //Identifier structName = result.declarationsConverter.getActualTaggedTypeName(parentStruct); // return //result.result.getObjCClass(parentStruct.getName()). // typeRef(//libMember(structName, libraryClassName, // inferCallBackName(s, true, true)//) // ); // } return findCallbackRef(s, libraryClassName); } public TypeRef findCallbackRef(FunctionSignature s, Identifier callerLibraryClass) { String library = s == null ? null : result.getLibrary(s); if (library == null) { return null; } // Struct parentStruct = s.findParentOfType(Struct.class); // if (parentStruct != null && (parentStruct.getType() == Struct.Type.ObjCClass || parentStruct.getType() == Struct.Type.ObjCProtocol)) { // Identifier structName = result.declarationsConverter.getActualTaggedTypeName(parentStruct); // return // typeRef(ident(structName, inferCallBackName(s, true, true))); // } Identifier identifier = s.getResolvedJavaIdentifier(); if (identifier == null) { throw new UnsupportedConversionException(s, null); } return typeRef(identifier); // return typeRef(libMember(result.getLibraryClassFullName(library), callerLibraryClass, inferCallBackName(s, true, true))); //typeRef(ident(result.getLibraryClassFullName(library), inferCallBackName(s, true))); } static TypeRef primRef(Element element, JavaPrim p) { if (p == null) { return null; } if (p.type == null) { throw new UnsupportedConversionException(element, "Primitive without known type for this runtime: " + p); } return new JavaPrimitive(p); // return new SimpleTypeRef(toString(p)); } boolean isResolved(SimpleTypeRef tr) { return tr != null && (tr.isMarkedAsResolved() || isResolved(tr.getName())); } boolean isResolved(Identifier i) { if (i == null || i.isPlain()) { return false; } return (i instanceof Identifier.QualifiedIdentifier) && Identifier.QualificationSeparator.Dot.equals(((Identifier.QualifiedIdentifier) i).getSeparator()); } public enum ConvType { Enum, Pointer, FunctionSignature, Primitive, Struct, NativeLong, NativeSize, NativeTime, ComplexDouble, Void, Callback, Default } static Map<String, Pair<Integer, Class<?>>> buffersAndArityByType = new LinkedHashMap<String, Pair<Integer, Class<?>>>(); static Map<String, Pair<Integer, Class<?>>> arraysAndArityByType = new LinkedHashMap<String, Pair<Integer, Class<?>>>(); static Set<String> objectMethodNames = new HashSet<String>(); static { for (Method method : Object.class.getDeclaredMethods()) { objectMethodNames.add(method.getName()); } Object[] data = new Object[]{ "char", Byte.TYPE, byte[].class, ByteBuffer.class, "Char", "long", Long.TYPE, long[].class, LongBuffer.class, "Long", "int", Integer.TYPE, int[].class, IntBuffer.class, "Int", "short", Short.TYPE, short[].class, ShortBuffer.class, "Short", "wchar_t", Character.TYPE, char[].class, CharBuffer.class, "WChar", "double", Double.TYPE, double[].class, DoubleBuffer.class, "Double", "float", Float.TYPE, float[].class, FloatBuffer.class, "Float", "bool", Boolean.TYPE, boolean[].class, null, "Bool" }; for (int arity : new int[]{1, 2, 4, 8, 16}) { String suffix = arity == 1 ? "" : arity + ""; for (int i = 0; i < data.length; i += 5) { String rawType = (String) data[i]; Class<?> scalClass = (Class<?>) data[i + 1]; Class<?> arrClass = (Class<?>) data[i + 2]; Class<?> buffClass = (Class<?>) data[i + 3]; String radix = (String) data[i + 4]; Pair<Integer, Class<?>> buffPair = new Pair<Integer, Class<?>>(arity, arity == 1 ? scalClass : buffClass), arrPair = new Pair<Integer, Class<?>>(arity, arity == 1 ? scalClass : arrClass); for (String type : new String[]{rawType + suffix, "u" + rawType + suffix}) { buffersAndArityByType.put(type, buffPair); arraysAndArityByType.put(type, arrPair); } } } } Pattern wstringPat = Pattern.compile("((__)?const ){1,2}wchar_t\\*"), stringPat = Pattern.compile("((__)?const ){1,2}char\\*"), wstringPtrPtrPat = Pattern.compile("((__)?const ){1,2}wchar_t\\*\\*"), stringPtrPtrPat = Pattern.compile("((__)?const ){1,2}char\\*\\*"); protected boolean isString(String typeRefAsString, boolean wide) { if (wide) { return wstringPat.matcher(typeRefAsString).matches() || result.config.charPtrAsString && typeRefAsString.equals("wchar_t*"); } else { return stringPat.matcher(typeRefAsString).matches() || result.config.charPtrAsString && typeRefAsString.equals("char*"); } } protected boolean isStringPtrPtr(String typeRefAsString, boolean wide) { if (wide) { return wstringPtrPtrPat.matcher(typeRefAsString).matches() || result.config.charPtrAsString && typeRefAsString.equals("wchar_t**"); } else { return stringPtrPtrPat.matcher(typeRefAsString).matches() || result.config.charPtrAsString && typeRefAsString.equals("char**"); } } static Map<String, Class<?>> predefObjCClasses = new LinkedHashMap<String, Class<?>>(); static { predefObjCClasses.put("id", ObjCObject.class);//org.rococoa.ID.class); predefObjCClasses.put("SEL", org.rococoa.Selector.class); predefObjCClasses.put("IMP", com.sun.jna.Pointer.class); predefObjCClasses.put("Class", ObjCClass.class); predefObjCClasses.put("Protocol", ObjCClass.class); predefObjCClasses.put("NSObject", NSObject.class); //predefObjCClasses.put("NSClass", NSClass.class); } public Identifier findObjCClassIdent(Identifier name) { if (name instanceof SimpleIdentifier) { SimpleIdentifier sname = (SimpleIdentifier) name; String n = sname.getName(); if (n.equals("id") && sname.getTemplateArguments().size() == 1/* && conversionMode != TypeConversionMode.NativeParameter && conversionMode != TypeConversionMode.NativeParameterWithStructsPtrPtrs*/) { Expression x = sname.getTemplateArguments().get(0); TypeRefExpression trx = x instanceof TypeRefExpression ? (TypeRefExpression) x : null; SimpleTypeRef str = trx.getType() instanceof SimpleTypeRef ? (SimpleTypeRef) trx.getType() : null; if (str != null) { name = str.getName(); } } } Class<?> class1 = predefObjCClasses.get(name.toString()); if (class1 != null) { return ident(class1); } Struct s = result.resolveObjCClass(name); if (s != null) { return result.objectiveCGenerator.getFullClassName(s); } return null; } public TypeRef findObjCClass(Identifier name) { return typeRef(findObjCClassIdent(name)); } protected TypeRef arrayRef(TypeRef tr) { ArrayRef arrayRef; if (tr instanceof ArrayRef) { arrayRef = (ArrayRef) tr; arrayRef.addDimension(new Expression.EmptyArraySize()); } else { arrayRef = new ArrayRef(tr); } return arrayRef; } Set<String> unknownTypes = new HashSet<String>(); public static <A, B> Pair<A, B> pair(A a, B b) { return new Pair<A, B>(a, b); } public static Pair<Expression, TypeRef> typed(Expression a, TypeRef b) { return new Pair<Expression, TypeRef>(a, b); } public boolean isString(Expression val) { return val instanceof Constant && ((Constant) val).getType() == Constant.Type.String; // TODO use typer + type annotations ! } public Constant.Type getConstantType(Expression expr) { if (!(expr instanceof Constant)) { return null; } return ((Constant) expr).getType(); } public abstract Expression getEnumItemValue(EnumItem enumItem, boolean forceConstant); public TypeRef convertToJavaType(Constant.Type type) { switch (type) { case Bool: return typeRef(Boolean.TYPE); case IntegerString: case UInt: case Int: return typeRef(Integer.TYPE); case LongString: case ULong: case Long: return typeRef(Long.TYPE); case Short: return typeRef(Short.TYPE); case Byte: return typeRef(Byte.TYPE); case Float: return typeRef(Float.TYPE); case Double: return typeRef(Double.TYPE); case String: return typeRef(String.class); default: return null; } } protected Expression sizeof(JavaPrim prim) { return prim.size.sizeof(prim); } protected Expression findEnumItem(EnumItem enumItem) { String library = result.getLibrary(enumItem); if (library == null) { return null; } Element parent = enumItem.getParentElement(); if (parent == null || !(parent instanceof Enum)) { return null; } Enum e = (Enum) parent; Identifier enumItemName = ident(enumItem.getName()); enumItemName.resolveLastSimpleIdentifier().setJavaStaticImportable(true); Identifier ident = ident(result.getLibraryClassFullName(library), result.declarationsConverter.getActualTaggedTypeName(e), enumItemName); return expr(typeRef(ident).setMarkedAsResolved(true)); } /// @see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html public static Set<String> JAVA_OBJECT_METHODS = new HashSet<String>(Arrays.asList( "notify", "notifyAll", "equals", "finalize", "getClass", "hashCode", "clone", "toString", "wait" // not allowed for function names )); public static Set<String> JAVA_KEYWORDS = new HashSet<String>(Arrays.asList( "null", "true", "false", "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while")); //static String keywords = " true false double float wait new null boolean return class public protected private "; public Identifier getValidJavaArgumentName(Identifier name) { return getValidJavaIdentifier(name); } public Identifier getValidJavaMethodName(Identifier name) { String nameStr = name.toString(); String newName = null; if (nameStr.matches("operator[^\\w]+")) { String op = nameStr.substring("operator".length()); //int nArgs = method.getArgs().size(); String suffix = null; java.lang.Enum<?> e = Expression.getAnyOperator(op); if (e == null) { if (op.equals("()")) { suffix = "parenthesis"; } else if (op.equals("[]")) { suffix = "brackets"; } else if (op.equals("->")) { suffix = "arrow"; } } else { suffix = e.name(); } if (suffix != null) { newName = "operator" + StringUtils.capitalize(suffix); } } else if (objectMethodNames.contains(nameStr)) { newName = name + "$"; }/* else if (nameStr.startsWith("~")) { newName = getValidJavaIdentifierString(ident(nameStr.substring(1))) + "Destructor"; }*/ if (newName == null) { newName = getValidJavaIdentifierString(name); } // else if (result.config.beautifyNames) { // newName = beautify(newName); // } return ident(newName); } String beautify(String name, boolean isType) { String newName = StringUtils.underscoredToCamel(name); if (!isType) { newName = StringUtils.uncapitalize(newName); } if (name.endsWith("_")) { newName += "$"; } return newName; } public boolean isJavaKeyword(String name) { return JAVA_KEYWORDS.contains(name) || JAVA_OBJECT_METHODS.contains(name); // not really keywords, but roughly same restrictions apply. } public Identifier getValidJavaIdentifier(Identifier name) { return ident(getValidJavaIdentifierString(name)); } public String getValidJavaIdentifierString(Identifier name) { if (name == null) { return null; } if (isJavaKeyword(name.toString())) { return name + "$"; } else { String newName = name.toString().replace('-', '_').replaceAll("[^\\w]", "\\$"); // if (result.config.beautifyNames) { // newName = beautify(newName); // } return newName; } } public static String toPrimString(JavaPrim prim) { return prim.name; } public Expression getJavaClassLitteralExpression(TypeRef tr) { JavaPrim prim = result.typeConverter.getPrimitive(tr); return prim != null ? classLiteral(prim.type) : typeLiteral(tr.clone()); } public Expression getJavaClassLitteralExpression() { throw new UnsupportedOperationException(getClass().getName() + "." + toString() + " not handled !"); } public Pair<Expression, TypeRef> convertExpressionToJava(Expression x, Identifier libraryClassName, boolean promoteNativeLongToLong, boolean forceConstants, Map<String, Pair<Expression, TypeRef>> mappings) throws UnsupportedConversionException { Pair<Expression, TypeRef> res = null; if (x instanceof Expression.AssignmentOp) { Pair<Expression, TypeRef> convTarget = convertExpressionToJava(((Expression.AssignmentOp) x).getTarget(), libraryClassName, promoteNativeLongToLong, forceConstants, mappings), convValue = convertExpressionToJava(((Expression.AssignmentOp) x).getValue(), libraryClassName, promoteNativeLongToLong, forceConstants, mappings); res = typed(expr(convTarget.getFirst(), Expression.AssignmentOperator.Equal, convValue.getFirst()), convTarget.getSecond()); } else if (x instanceof Expression.BinaryOp) { Expression.BinaryOp bop = (Expression.BinaryOp) x; Pair<Expression, TypeRef> conv1 = convertExpressionToJava(bop.getFirstOperand(), libraryClassName, promoteNativeLongToLong, forceConstants, mappings), conv2 = convertExpressionToJava(bop.getSecondOperand(), libraryClassName, promoteNativeLongToLong, forceConstants, mappings); if (conv1 != null && conv2 != null) { TypeRef t1 = conv1.getSecond(), t2 = conv2.getSecond(); Expression x1 = conv1.getFirst(), x2 = conv2.getFirst(); String s1 = String.valueOf(t1), s2 = String.valueOf(t2); TypeRef tr = null; if (bop.getOperator().givesBool) { tr = typeRef(boolean.class); } else { if (s1.equals(s2)) { tr = t1; } else { // t1 & t2 are already java primitives... JavaPrim p1 = "long".equals(t1.toString()) ? JavaPrim.Long : getPrimitive(t1), p2 = "long".equals(t2.toString()) ? JavaPrim.Long : getPrimitive(t2); if (p1 != null && p2 != null) { switch (bop.getOperator()) { case LeftShift: case RightShift: case SignedRightShift: tr = t1; break; default: for (JavaPrim p : new JavaPrim[]{ JavaPrim.Double, JavaPrim.Float, JavaPrim.Long, JavaPrim.NativeSize, JavaPrim.NativeLong, JavaPrim.Int, JavaPrim.Short, JavaPrim.Byte }) { if (p1 == p || p2 == p) { if (promoteNativeLongToLong && (p == JavaPrim.NativeLong || p == JavaPrim.NativeSize)) { p = JavaPrim.Long; } tr = primRef(x, p); break; } } } } } } res = typed(expr(x1, ((Expression.BinaryOp) x).getOperator(), x2), tr); } } else if (x instanceof Expression.UnaryOp) { Expression.UnaryOperator op = ((Expression.UnaryOp) x).getOperator(); if (op == Expression.UnaryOperator.Not) { throw new UnsupportedConversionException(x, null); // TODO handle this properly ? } Pair<Expression, TypeRef> conv = convertExpressionToJava(((Expression.UnaryOp) x).getOperand(), libraryClassName, promoteNativeLongToLong, forceConstants, mappings); res = typed(expr(op, conv.getFirst()), conv.getSecond()); } else if (x instanceof Expression.Constant) { Class<?> c = null; Expression.Constant jc = ((Expression.Constant) x).asJava(); switch (jc.getType()) { case Byte: c = Byte.TYPE; break; case Char: c = Character.TYPE; break; case Double: c = Double.TYPE; break; case Float: c = Float.TYPE; break; case Int: case UInt: case IntegerString: c = Integer.TYPE; break; case ULong: case Long: case LongString: c = Long.TYPE; break; case Short: c = Short.TYPE; break; case String: c = String.class; break; } if (c != null) { res = typed(((Expression.Constant) x).asJava(), typeRef(c)); } } else if (x instanceof Expression.TypeRefExpression) { // The parser might recognize enum items incorrectly as a TypeRefExpression... Expression.TypeRefExpression tre = (Expression.TypeRefExpression) x; TypeRef tr = tre.getType(); if (tr instanceof TypeRef.SimpleTypeRef) { TypeRef.SimpleTypeRef str = (TypeRef.SimpleTypeRef) tr; Identifier name = str.getName(); if (name != null) { if (result.enumItemsFullName.contains(name)) { res = typed(tre, typeRef(Integer.TYPE)); } // res = convertVariableRefToJava(name, libraryClassName, promoteNativeLongToLong); } } if (res == null) { if (tr.isMarkedAsResolved()) { res = typed(tre, tr); } // } else { // TypeRef conv = convertTypeToJNA(tr, TypeConversionMode.ExpressionType, libraryClassName); // res = typed(new Expression.TypeRefExpression(conv), conv); // } } } else if (x instanceof Expression.VariableRef) { Identifier name = ((Expression.VariableRef) x).getName(); Pair<Expression, TypeRef> mapping = mappings == null ? null : mappings.get(name.toString()); if (mapping != null) { res = mapping; } else { res = convertVariableRefToJava(name, libraryClassName, promoteNativeLongToLong, forceConstants); } } if (res == null) { // return convertExpressionToJava(x); throw new UnsupportedConversionException(x, null); } if (res.getFirst() == null) { return null; } res.getFirst().setParenthesis(x.getParenthesis()); return (Pair<Expression, TypeRef>) res; } static class EnumItemResult { public Enum.EnumItem originalItem; public Expression convertedValue, unconvertedValue, constantValue; public String comments; public String exceptionMessage; public Declaration errorElement; } protected Map<String, EnumItemResult> getEnumValuesAndCommentsByName(Enum e, Identifier libraryClassName) { Map<String, EnumItemResult> ret = new LinkedHashMap<String, EnumItemResult>(); Integer lastAdditiveValue = null; Expression lastRefValue = null; boolean failedOnceForThisEnum = false; Map<String, Pair<Expression, TypeRef>> mappings = new LinkedHashMap<String, Pair<Expression, TypeRef>>(); for (com.ochafik.lang.jnaerator.parser.Enum.EnumItem item : e.getItems()) { EnumItemResult res = new EnumItemResult(); res.originalItem = item; try { if (item.getArguments().isEmpty()) { // no explicit value if (lastRefValue == null) { if (lastAdditiveValue != null) { lastAdditiveValue++; res.unconvertedValue = expr(lastAdditiveValue); } else { if (item == e.getItems().get(0)) { lastAdditiveValue = 0; res.unconvertedValue = expr(lastAdditiveValue); } else { res.unconvertedValue = null; } } } else { // has a last reference value if (lastAdditiveValue != null) { lastAdditiveValue++; } else { lastAdditiveValue = 1; } res.unconvertedValue = expr( lastRefValue.clone(), Expression.BinaryOperator.Plus, expr(lastAdditiveValue)); } } else { // has an explicit value failedOnceForThisEnum = false;// reset skipping lastAdditiveValue = null; lastRefValue = item.getArguments().get(0); res.unconvertedValue = lastRefValue; if (lastRefValue instanceof Expression.Constant) { try { lastAdditiveValue = ((Expression.Constant) lastRefValue).asInteger(); lastRefValue = null; } catch (Exception ex) { } } } res.convertedValue = result.typeConverter.convertExpressionToJava(res.unconvertedValue, libraryClassName, true, false, mappings).getFirst(); res.constantValue = result.typeConverter.convertExpressionToJava(res.unconvertedValue, libraryClassName, true, true, mappings).getFirst(); mappings.put(item.getName(), typed(res.constantValue, typeRef(int.class))); } catch (Exception ex) { failedOnceForThisEnum = true; res.exceptionMessage = ex.toString(); } failedOnceForThisEnum = failedOnceForThisEnum || res.errorElement != null; if (failedOnceForThisEnum) { res.errorElement = result.declarationsConverter.skipDeclaration(item); } ret.put(item.getName(), res); } return ret; } private Pair<Expression, TypeRef> convertVariableRefToJava(Identifier name, Identifier libraryClassName, boolean promoteNativeLongToLong, boolean forceConstants) { if (name != null) { Define define = result.defines.get(name); if (define != null && define.getValue() != null) { if (name.toString().equals(define.getValue().toString())) { return null; // avoid some nasty loops } else { Expression defineValue = define.getValue(); if (defineValue instanceof Expression.Constant) { Expression.Constant constant = (Expression.Constant) defineValue; return typed(findDefine(name), convertToJavaType(constant.getType())); } return convertExpressionToJava(defineValue, libraryClassName, promoteNativeLongToLong, forceConstants, null); } } else { String sname = name.toString(); if (sname.equals("True") || sname.equals("true")) { return typed(expr(Expression.Constant.Type.Bool, true), primRef(define, JavaPrim.Boolean)); } else if (sname.equals("False") || sname.equals("false")) { return typed(expr(Expression.Constant.Type.Bool, false), primRef(define, JavaPrim.Boolean)); } else { Enum.EnumItem enumItem = result.enumItems.get(name); if (enumItem != null) { return typed(getEnumItemValue(enumItem, forceConstants), typeRef(Integer.TYPE)); } else { VariablesDeclaration constant = result.globalVariablesByName.get(name); if (constant != null) { return typed(varRef(findRef(name, constant, libraryClassName, true)), null); } else { return typed(new Expression.VariableRef(name), null); } } } } } return null; } public Identifier getTaggedTypeIdentifierInJava(TaggedTypeRef s) { return result.resolveFullTaggedTypeRef(s).getResolvedJavaIdentifier(); } public Identifier computeTaggedTypeIdentifierInJava(TaggedTypeRef s) { Identifier name = result.declarationsConverter.getActualTaggedTypeName(s); if (name == null) { return null; } String library = result.getLibrary(s); if (library == null) { return null; } name = name.clone(); Struct parentStruct = s.findParentOfType(Struct.class); //Struct parentStruct = s.findParentOfType(Struct.class); if (parentStruct != null && parentStruct != s) { return ident(getTaggedTypeIdentifierInJava(parentStruct), name); } else if ((s instanceof Struct) && (result.config.putTopStructsInSeparateFiles)) {// || result.config.runtime == JNAeratorConfig.Runtime.BridJ)) { return packageMember(result.getLibraryPackage(library), name); //return ident(result.getLibraryPackage(library), name); } else { return libMember(result.getLibraryClassFullName(library), null, name); } } public Identifier computeCallbackIdentifierInJava(FunctionSignature fs) { Identifier name = inferCallBackName(fs, false, false, null); if (name == null) { return null; } String library = result.getLibrary(fs); if (library == null) { return null; } name = name.clone(); Struct parentStruct = fs.findParentOfType(Struct.class); //Struct parentStruct = s.findParentOfType(Struct.class); if (parentStruct != null) { return ident(getTaggedTypeIdentifierInJava(parentStruct), name); } else { return libMember(result.getLibraryClassFullName(library), null, name); } } }